import cv2
import numpy as np


def cutByOval(img, radius, centerX, centerY):
    """根据最低半径radius来裁剪椭圆形的圆
    img为numpy的图片数组"""
    # img = cv2.cvtColor(img, cv2.IMREAD_UNCHANGED)
    radius = int(radius)
    centerX = int(centerX)
    centerY = int(centerY)

    height = img.shape[0]
    width = img.shape[1]

    # 根据宽高比来计算长轴和短轴
    longAxis = int(radius * (height / width))  # 长轴
    shortAxis = radius  # 短轴

    # oval = np.zeros((320, 320, 3), np.uint8)  # 生成一个空灰度图像
    # oval = np.zeros((height, width, 1), dtype=np.uint8)
    oval = np.zeros((height, width, 1), np.uint8)
    # 绘制一个椭圆
    ptCenter = (centerX, centerY)  # 中心点位置
    axesSize = (longAxis, shortAxis)  # 长轴和短轴半径
    rotateAngle = 90  # 旋转角度为 90
    startAngle = 0
    endAngle = 360
    point_color = (1)  # BGR
    thickness = -1  # -1为填充
    lineType = 4
    cv2.ellipse(oval, ptCenter, axesSize, rotateAngle, startAngle, endAngle, point_color, thickness,
                lineType)
    # print(type(oval), oval.shape)

    # 创建透明通道图层
    merge = np.zeros((height, width, 4), np.uint8)

    # 复制前3个通道
    merge[:, :, 0] = np.multiply(img[:, :, 0], oval[:, :, 0])
    merge[:, :, 1] = np.multiply(img[:, :, 1], oval[:, :, 0])
    merge[:, :, 2] = np.multiply(img[:, :, 2], oval[:, :, 0])

    # 设置α通道的不透明部分
    oval[oval == 1] = 255
    merge[:, :, 3] = oval[:, :, 0]

    # 按比例裁剪宽高的透明像素
    # 透明像素的高度
    alphaHeight = int((height - (longAxis * 2)) / 2)
    if alphaHeight > 0:
        merge = merge[alphaHeight:int(height - alphaHeight), 0:width]
    # merge = cv2.resize(merge, (shortAxis * 2, longAxis * 2), interpolation=cv2.INTER_AREA)
    # merge = cv2.cvtColor(merge, cv2.COLOR_BGR2BGRA)
    # print(type(merge), merge.shape)

    # cv2.imshow("test", oval)
    # cv2.imshow("test", merge)
    # cv2.imwrite("1111.png", merge)
    # while True:
    #     if cv2.waitKey(5) & 0xFF == 27:
    #         cv2.destroyAllWindows()
    #         break;

    return merge


# def addAlphaToObj(img, alpha=255):
# #     """给图片附加透明背景
# #     alpha:透明度"""
# #     b_channel, g_channel, r_channel = cv2.split(img)
# #
# #     alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 255
# #     # 最小值为0
# #     alpha_channel[:, :] = 255
# #
# #     img_BGRA = cv2.merge((b_channel, g_channel, r_channel, alpha_channel))
# #     return img_BGRA

def add_transparent_background(image):
    # 获取图像的高度和宽度
    height, width = image.shape[:2]

    # 获取图像的高度和宽度
    height, width = image.shape[:2]

    # 如果图像没有 alpha 通道，则创建一个具有透明背景的新图像
    if image.shape[2] == 3:
        # 添加 alpha 通道
        image = cv2.cvtColor(image, cv2.COLOR_BGR2BGRA)

    # 创建一个具有透明背景的新图像
    transparent_image = np.zeros((height, width, 4), dtype=np.uint8)

    # 将原始图像的 RGBA 通道复制到新图像的 RGBA 通道
    transparent_image[:, :, :4] = image

    # 保存具有透明背景的图像
    # cv2.imwrite(output_path, transparent_image)
    return transparent_image


def alphaAddWhiteBg(img):
    """给透明图片添加白色背景"""
    sp = img.shape
    width = sp[0]
    height = sp[1]
    for yh in range(height):
        for xw in range(width):
            color_d = img[xw, yh]
            if (color_d[3] == 0):
                img[xw, yh] = [255, 255, 255, 255]
    return img


def pastImgToBg(bgImg, img, x, y):
    """我自己些的贴图方式"""
    """把图片粘贴到背景图上 x,y 为笛卡尔坐标系左上角"""
    height = img.shape[0]
    width = img.shape[1]
    bgImg[x:height, y:width] = img
    return bgImg


def pastImgToBg2(bgImg, img, x, y):
    """chatgpt的贴图方式"""
    # 确保小图不大于大图，并将小图的大小与大图相同
    if img.shape[0] > bgImg.shape[0] or img.shape[1] > bgImg.shape[1]:
        raise ValueError("Foreground image must be smaller than background image")
    fg_resized = np.zeros_like(bgImg)
    fg_resized[:img.shape[0], :img.shape[1], :] = img

    # 创建一个四通道的数组，将小图复制到前三个通道，透明度通道设置为小图的透明度通道
    output = np.zeros_like(bgImg)
    output[:, :, :3] = fg_resized[:, :, :3]
    output[:, :, 3] = fg_resized[:, :, 3]

    # 将小图覆盖在大图的指定位置
    # x, y = 100, 100  # 小图的左上角在大图中的位置
    bgImg[x:x + img.shape[0], y:y + img.shape[1], :] = output[:img.shape[0],
                                                       :img.shape[1], :]
    return bgImg


def convert_1to3channel(img_gray):
    """单通道图转换成多通道图"""
    # 创建一个零通道图像，与单通道图像的大小相同
    height, width = img_gray.shape[:2]
    img_bgr = np.zeros((height, width, 3), dtype=np.uint8)

    # 将单通道图像合并成多通道图像
    img_bgr[:, :, 0] = img_gray  # 将单通道图像的值赋给蓝通道
    img_bgr[:, :, 1] = img_gray  # 将单通道图像的值赋给绿通道
    img_bgr[:, :, 2] = img_gray  # 将单通道图像的值赋给红通道

    return img_bgr


def convert_1to4channel(img_gray):
    # 创建一个零通道图像，与单通道图像的大小相同，但通道数为4
    height, width = img_gray.shape[:2]
    img_rgba = np.zeros((height, width, 4), dtype=np.uint8)

    # 将单通道图像的值赋给新的通道
    img_rgba[:, :, 0] = img_gray  # 将单通道图像的值赋给蓝通道
    img_rgba[:, :, 1] = img_gray  # 将单通道图像的值赋给绿通道
    img_rgba[:, :, 2] = img_gray  # 将单通道图像的值赋给红通道
    img_rgba[:, :, 3] = 255  # 将 alpha 通道设置为不透明

    return img_rgba


def replace_black_with_transparent(rgba_image):
    """把图片中黑色像素替换成透明"""
    # 遍历图片的每个像素
    for y in range(rgba_image.shape[0]):
        for x in range(rgba_image.shape[1]):
            # 检查像素是否为黑色
            if np.all(rgba_image[y, x] == [0, 0, 0, 255]):
                # 将像素透明度设置为0（完全透明）
                rgba_image[y, x, 3] = 0

    return rgba_image


def cutByPosition(img, pos):
    """根据坐标位置不规则裁剪图片"""
    # pos = [[(500, 500), (40, 20), (70, 80), (5, 100)]]
    mask = np.zeros((img.shape[0], img.shape[1], 4), dtype=np.uint8)

    height = img.shape[0]
    width = img.shape[1]
    channels = img.shape[2]
    # 输入点的坐标
    roi_corners = np.array(pos, dtype=np.int32)
    ignore_mask_color = (255,) * channels
    # 创建mask层
    cv2.fillPoly(mask, roi_corners, ignore_mask_color)
    # 为每个像素进行与操作，除mask区域外，全为0
    masked_image = cv2.bitwise_and(img, mask)
    # 分别找到坐标的左上右下最远距离
    left = width
    right = 0
    top = height
    bottom = 0
    for f in pos:
        for r in f:
            if r[0] < left:
                left = r[0]
            if r[0] > right:
                right = r[0]
            if r[1] < top:
                top = r[1]
            if r[1] > bottom:
                bottom = r[1]
    # print(left, top, right, bottom)
    masked_image = masked_image[top:bottom, left:right]
    return masked_image


def resizeImg(img, target_width=512, target_height=512):
    """等比例缩放图片到制定的尺寸
        # 定义目标尺寸
        target_width = 512
        target_height = 512
    """

    # 定义目标尺寸

    # 计算缩放比例
    scale = min(target_width / img.shape[1], target_height / img.shape[0])

    # 计算缩放后的新尺寸
    new_width = int(img.shape[1] * scale)
    new_height = int(img.shape[0] * scale)

    # 缩放图像
    resized_img = cv2.resize(img, (new_width, new_height), interpolation=cv2.INTER_AREA)

    return resized_img


def erode(image):
    """腐蚀图像"""
    # image = cv2.imread('5.png', cv2.IMREAD_GRAYSCALE)

    # 创建一个腐蚀核
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))  # 可以根据需求调整核的大小

    # 执行图像腐蚀
    eroded_image = cv2.erode(image, kernel, iterations=1)  # 迭代次数可根据需求进行调整

    # cv2.imwrite("test.png", eroded_image)
    return eroded_image


# opencv的BGR转成带透明图层的图片,
def BGR_to_ABGR(img, transparency_value=100):
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGBA)
    return img


def trim_transparent_edges(image):
    """裁切掉四周的透明部分"""
    if len(image.shape) <= 2:
        add_transparent_background(image)
    height, width, _ = image.shape
    if _ >= 4:  # 最后一个是层数
        # 带有alpha通道才进行裁剪
        # 将图像转换为RGBA格式
        image_rgba = cv2.cvtColor(image, cv2.COLOR_BGR2BGRA)

        # 查找非透明像素的边界
        coords = cv2.findNonZero(image_rgba[:, :, 3])

        if coords is not None:
            # 获取边界的坐标范围
            x, y, w, h = cv2.boundingRect(coords)

            # 裁剪图像并删除四周透明像素
            trimmed_image = image[y:y + h, x:x + w]

            return trimmed_image
        else:
            return None
    else:
        return image


def resize_image(img, target_size):
    """缩放图片让最长边不超过target_size"""
    # 获取图片的高度和宽度
    height, width = img.shape[:2]

    # 计算缩放比例
    if height > width:
        ratio = target_size / height
    else:
        ratio = target_size / width

    # 缩放图片
    resized_img = cv2.resize(img, (int(width * ratio), int(height * ratio)))

    return resized_img


if __name__ == '__main__':
    img = cv2.imread('images/1.jpg')
    img = cutByOval(img, img.shape[1] / 2, img.shape[1] / 2,
                    img.shape[0] / 2)
    cv2.imshow("test", img)

    while True:
        if cv2.waitKey(5) & 0xFF == 27:
            cv2.destroyAllWindows()
            break;
